﻿using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Home.MobileSales.ImpExpData.Core;
using Home.MobileSales.ImpExpData.InterfaceView;
using Home.Mobilesales.Common;

namespace Home.MobileSales.ImpExpData.Presenter
{
    class ExportImportPresenter
    {
        private IExportImportView _view;
        private Thread thread;

        private delegate bool BoolDelegate();
        private delegate TypeExport TypeExportDelegate();
        private delegate DateTime DateTimeDelegate();
        private delegate void GoMethod();

        private delegate void SetInteger(int i);
        private delegate void SetString(string str);
        private delegate void SetStringBool(string str, bool er);

        private bool GetBoolParameter(BoolDelegate callback)
        {
            return (bool)((Control)_view).Invoke(callback);
        }

        private TypeExport GetTypeExportParameter (TypeExportDelegate callback)
        {
            return (TypeExport)((Control)_view).Invoke(callback); 
        }
        
        private DateTime GetDateTimeParameter(DateTimeDelegate callback)
        {
            return (DateTime)((Control)_view).Invoke(callback);
        }

        private void SetStatus (string st, bool error)
        {
            ((Control)_view).Invoke(new SetString(_view.SetStatusLabel), st);
        }

        private void SetLog(string st, bool error)
        {
            ((Control)_view).Invoke(new SetStringBool(_view.AddLogListBox), st, error);
        }

        public ExportImportPresenter(IExportImportView view, bool isImport)
        {
            _view = view;
            _view.IsImport = isImport;
            _view.Execute += Execute;
            _view.Abort += AbortLoad;
        }

        private List<IExportImportData> buildImportList()
        {
            List<IExportImportData> importData = new List<IExportImportData>();
            string file;
            string path = Settings.GetInstance().ImportPath;

            if (GetBoolParameter(() => _view.IsAllGoods))
            {
                //Groups
                ImportDataTable importTable = new ImportDataTable();
                importTable.Name = "Групи товарів";
                file = path + "\\Groups.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "Groups";
                importData.Add(importTable);


                //TradeMarks
                importTable = new ImportDataTable();
                importTable.Name = "Торгові марки";
                file = path + "\\Trademarks.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "Trademarks";
                importData.Add(importTable);


                //Goods
                importTable = new ImportDataTable();
                importTable.Name = "Товари";
                file = path + "\\Goods.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "Goods";
                importData.Add(importTable);

                //remains
                importTable = new ImportDataTable();
                importTable.Name = "Залишки";
                file = path + "\\Remains.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "Remains";
                importData.Add(importTable);

            }
            if (GetBoolParameter(() => _view.IsRemaining))
            {
                ImportDataTableZero importGoods = new ImportDataTableZero();
                importGoods.Name = "Залишки";
                importGoods.ColumnByZero = "Quantity";
                file = path + "\\Remains.xml";
                importGoods.FileName = new FileInfo(file);
                importGoods.TableName = "Remains";
                importData.Add(importGoods);
            }

            if (GetBoolParameter(() => _view.IsBuyers))
            {
                //Buyers
                ImportDataTable importTable = new ImportDataTable();
                importTable.Name = "Список клієнтів";
                file = path + "\\Buyers.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "Buyers";
                importData.Add(importTable);

                //BuyPoint
                importTable = new ImportDataTable();
                importTable.Name = "Торгові точки";
                file = path + "\\BuyPoints.xml";
                importTable.FileName = new FileInfo(file);
                importTable.TableName = "BuyPoints";
                importData.Add(importTable);
            }           

            else if (GetBoolParameter(() => _view.IsDebts))
            {
                ImportColumnsZero importGoods = new ImportColumnsZero();
                importGoods.Columns = new string[] { "IdBuyPoint", "Debts" };
                importGoods.Name = "Заборгованість";
                importGoods.ColumnByZero = "Debts";
                file = path + "\\Debts.xml";
                importGoods.FileName = new FileInfo(file);
                importGoods.TableName = "BuyPoints";
                importData.Add(importGoods);
            }
            return importData;
        }

        private List<IExportImportData> buildExportList()
        {
            string path = Settings.GetInstance().ExportPath;
            List<IExportImportData> exportsData = new List<IExportImportData>();
            if (GetBoolParameter(() => _view.IsVisits))
            {
                switch (GetTypeExportParameter(()=>_view.GetTypeVisitExport))
                {
                    case TypeExport.OnlyNew:
                        {
                            exportsData.Add(new ExportNewVisits
                                                {FileName = new FileInfo(path + "\\"+DateTime.Now.ToString("ddMMyyHHmmss-")+"Visits.xml"), Name = "Візити і продажі"});
                            break;
                        }
                    case TypeExport.SingleDate:
                        {
                            ExportVisitsByDate exports = new ExportVisitsByDate();
                            exports.BeginDate = GetDateTimeParameter(() => _view.SingleDate);
                            exports.Name = "Візити і продажі";
                            exports.FileName = new FileInfo(path + "\\" + DateTime.Now.ToString("ddMMyyHHmmss-") + "Visits.xml");
                            exports.EndDate = exports.BeginDate.AddDays(0.99);
                            exportsData.Add(exports);
                            break;
                        }
                    case TypeExport.RepeatDate:
                        {
                            exportsData.Add(new ExportVisitsByDate
                            {
                                BeginDate = GetDateTimeParameter(() => _view.BeginDate),
                                EndDate = GetDateTimeParameter(()=>_view.EndDate),
                                FileName = new FileInfo(path + "\\"+DateTime.Now.ToString("ddMMyyHHmmss-")+"Visits.xml"),
                                Name = "Візити і продажі"
                            });
                            break;
                        }
                }
            }
            return exportsData;
        }

        private void LoadFromFtp (List<IExportImportData> processingData)
        {
            using (FtpWork ftp = new FtpWork())
            {
                ftp.ShowStatus += SetStatus;
                ftp.ShowLog += SetLog;
                ftp.OpenConnection(Settings.GetInstance().FtpUrl, (ushort) Settings.GetInstance().FtpPort,
                                   Settings.GetInstance().FtpLogin, Settings.GetInstance().FtpPassword,
                                   Settings.GetInstance().IsPassivMode);

                for (int i = 0; i < processingData.Count; )
                {
                    if (!ftp.GetFileFromFtp(Settings.GetInstance().FtpImportPath + "/" + processingData[i].FileName.Name,
                                            Settings.GetInstance().ImportPath + @"\" + processingData[i].FileName.Name, true))
                    {
                        processingData.Remove(processingData[i]);
                        continue;
                    }
                    i++;
                }
            }

        }
        
        private void LoadToFtp (List<IExportImportData> processingData)
        {
            using (FtpWork ftp = new FtpWork())
            {
                ftp.ShowStatus += SetStatus;
                ftp.ShowLog += SetLog;
                ftp.OpenConnection(Settings.GetInstance().FtpUrl, (ushort)Settings.GetInstance().FtpPort,
                                   Settings.GetInstance().FtpLogin, Settings.GetInstance().FtpPassword,
                                   Settings.GetInstance().IsPassivMode);

                for (int i = 0; i < processingData.Count; )
                {
                    if (!ftp.PutFilesToFTP(Settings.GetInstance().FtpExportPath + "/" + processingData[i].FileName.Name,
                                            Settings.GetInstance().ExportPath + @"\" + processingData[i].FileName.Name))
                    {
                        processingData.Remove(processingData[i]);
                        continue;
                    }
                    i++;
                }
            }
        }

        private void ExecuteData (List<IExportImportData> processingData)
        {
            int status = 0;
            ((Control)_view).Invoke(new SetInteger(_view.SetStatusMax), processingData.Count);
            ((Control)_view).Invoke(new SetInteger(_view.SetStatusPosition), 0);
            for (int i = 0; i < processingData.Count; )
            {
                IExportImportData dataInProcess = processingData[i];
                try
                {
                    SetStatus(dataInProcess.Name, false);
                    dataInProcess.Execute();
                    SetLog(string.Format("{0} - Оброблено", dataInProcess.Name), false);
                    i++;
                }
                catch (Exception ex)
                {
                    SetLog(string.Format("{0} - Помилка при обробці", dataInProcess.Name), true);
                    if (
                        MessageBox.Show(
                            string.Format("Помилка при обробці {0} файлу {1}продовжити ?", dataInProcess.Name,
                                          dataInProcess.FileName), string.Empty, MessageBoxButtons.YesNo,
                            MessageBoxIcon.Hand, MessageBoxDefaultButton.Button2) == DialogResult.No)
                    {
                        ((Control)_view).Invoke(new GoMethod(_view.ErrorData));
                        throw (ex);
                    }
                    processingData.Remove(processingData[i]);

                }
                finally
                {
                    status++;
                    ((Control)_view).Invoke(new SetInteger(_view.SetStatusPosition), status);
                }
            }
        }

        private void ImportData()
        {
            List<IExportImportData> processingData = buildImportList();
            if (!GetBoolParameter(() => _view.OnlyExecute))
                LoadFromFtp(processingData);
            ExecuteData(processingData);
            foreach (var exportData in processingData)
            {
                if (!Settings.GetInstance().IsSaveFiles)
                    exportData.FileName.Delete();
                else
                {
                    DirectoryInfo arcDir = exportData.FileName.Directory.CreateSubdirectory("Arc");
                    exportData.FileName.MoveTo(arcDir.FullName + "\\" + DateTime.Now.ToString("ddMMyyHHmmss-" + exportData.FileName.Name));
                }
            }
        }

        private void ExportData()
        {
            List<IExportImportData> processingData = buildExportList();
            ExecuteData(processingData);
            if (!GetBoolParameter(() => _view.OnlyExecute))
            {
                LoadToFtp(processingData);
                foreach (var exportData in processingData)
                {
                    if (!Settings.GetInstance().IsSaveFiles)
                        try
                        {
                            exportData.FileName.Delete();
                        }
                        catch (Exception)
                        {

                            throw new OtherException("Неможливо видалити файл");
                        }

                    else
                    {
                        try
                        {
                            DirectoryInfo arcDir = exportData.FileName.Directory.CreateSubdirectory("Arc");
                            exportData.FileName.MoveTo(arcDir.FullName + "\\" + exportData.FileName.Name);
                        }
                        catch (Exception)
                        {

                            throw new OtherException("Неможливо перемістити файл");
                        }

                    }
                }
            }
        }

        private void WorkData()
        {
            try
            {
                if (GetBoolParameter(() => _view.IsImport))
                {
                    ImportData();
                }
                else
                {
                    ExportData();
                }
                ((Control)_view).Invoke(new GoMethod(_view.EndData));
                
            }
            catch(Exception ex)
            {
                ExceptionWork.ExeptionProcess(ex);
            }
        }

        public void AbortLoad (object sender, EventArgs e)
        {
            thread.Abort();
            _view.ErrorData();
        }

        public void Execute(object sender, EventArgs e)
        {
            thread = new Thread(new ThreadStart(WorkData));
            thread.IsBackground = true;
            thread.Start();
        }
    }
}
